﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using TestBat.IModels.Domain;
using TestBat.IModels.Models;
using TestBat.IViewModels.Base;
using TestBat.IViewModels.Dialogs;
using TestBat.IViewModels.Factories;
using TestBat.IViewModels.Workspaces.Tasks;
using TestBat.Models.Exceptions;
using TestBat.ServiceLocator;
using TestBat.ViewModels.Attributes;
using TestBat.ViewModels.Base;
using TestBat.ViewModels.Base.Commands;
using TestBat.ViewModels.Dialogs;

namespace TestBat.ViewModels.Workspaces.Tasks
{
    public abstract class TaskFolderViewModel : TreeItemViewModel, ITaskFolderViewModel
    {
        public TaskFolderViewModel(ITaskFolder taskFolder, ITaskFolderModel taskFolderModel,
            ITaskViewModelFactory taskViewModelFactory, ILeafTaskFolderViewModelFactory taskFolderViewModelFactory)
        {
            this.taskFolder = taskFolder;
            this.taskFolderModel = taskFolderModel;
            this.taskViewModelFactory = taskViewModelFactory;
            this.taskFolderViewModelFactory = taskFolderViewModelFactory;
        }

        public virtual ObservableCollection<ITreeItemViewModel> Children
        {
            get
            {
                if (children == null)
                {
                    children = new ObservableCollection<ITreeItemViewModel>();

                    try
                    {
                        // add folders
                        IList<ILeafTaskFolder> folders = taskFolderModel.GetChildren(taskFolder);
                        foreach (var item in folders)
                            AddNode(item);

                        // add tasks
                        IList<ITask> tasks = taskFolderModel.GetTasks(taskFolder);
                        foreach (var item in tasks)
                            AddNode(item);
                    }
                    catch (BusinessException e)
                    {
                        // show error to user
                        DefaultServiceLocator.Get<IDialogMediator>().DialogViewModel = new BusinessErrorDialogViewModel(e);
                    }
                }

                return children;
            }
        }

        public virtual int TaskCount
        {
            get { return taskFolderModel.GetTaskCount(taskFolder); }
        }

        public virtual ITaskFolder TaskFolder
        {
            get { return taskFolder; }
        }

        public virtual ICommand CreateSubfolderCommand
        {
            get { return new RelayCommand(c => CreateSubfolder()); }
        }

        public virtual ICommand CreateEssayTaskCommand
        {
            get
            {
                return new RelayCommand(c => CreateEssayTask());
            }
        }

        public virtual ICommand CreateMultipleChoiceTaskCommand
        {
            get
            {
                return new RelayCommand(c => CreateMultipleChoiceTask());
            }
        }

        public virtual ICommand CreateMultipleResponseTaskCommand
        {
            get
            {
                return new RelayCommand(c => CreateMultipleResponseTask());
            }
        }

        protected virtual void AddNode(ITask task)
        {
            var taskViewModel = taskViewModelFactory.Create(task);

            taskViewModel.PreSelect = PreSelect;
            taskViewModel.OnRemove = RemoveNode;
            children.Add(taskViewModel);
        }

        protected virtual void AddNode(ILeafTaskFolder taskFolder)
        {
            var taskFolderViewModel = taskFolderViewModelFactory.Create(taskFolder);

            taskFolderViewModel.PreSelect = PreSelect;
            taskFolderViewModel.OnRemove = RemoveNode;
            children.Add(taskFolderViewModel);
        }

        protected virtual void RemoveNode(ITreeItemViewModel node)
        {
            children.Remove(node);
        }

        [BusinessErrorDialog]
        private void CreateSubfolder()
        {
            // create subfolder
            ILeafTaskFolder tf = taskFolderModel.CreateSubfolder(taskFolder);

            // add to (visual) tree
            AddNode(tf);
        }

        [BusinessErrorDialog]
        private void CreateEssayTask()
        {
            // create task
            IEssayTask et = taskFolderModel.CreateTask<IEssayTask>(taskFolder);

            // add to (visual) tree
            AddNode(et);
        }

        [BusinessErrorDialog]
        private void CreateMultipleChoiceTask()
        {
            // create task
            IMultipleChoiceTask et = taskFolderModel.CreateTask<IMultipleChoiceTask>(taskFolder);

            // add to (visual) tree
            AddNode(et);
        }

        [BusinessErrorDialog]
        private void CreateMultipleResponseTask()
        {
            // create task
            IMultipleResponseTask et = taskFolderModel.CreateTask<IMultipleResponseTask>(taskFolder);

            // add to (visual) tree
            AddNode(et);
        }

        [BusinessErrorDialog]
        public override void OnLostFocus()
        {
            // revert changes
            taskFolderModel.Revert(taskFolder);
        }

        protected ObservableCollection<ITreeItemViewModel> children;

        protected ITaskFolder taskFolder;
        protected ITaskFolderModel taskFolderModel;

        private readonly ITaskViewModelFactory taskViewModelFactory;
        private readonly ILeafTaskFolderViewModelFactory taskFolderViewModelFactory;
    }
}
